package java_thinking.unit_17;

/**
 * @Desc:
 *      必看：https://blog.csdn.net/zxt0601/article/details/77429150
 *      1.底层数据结构也是Node<K , V>，但是LinkedHashMap添加了两个域Entry<K,V> before, after;，用于实现链表功能；
 *
 *      2.与HashMap相同点：
 *          2.1 都是基于哈希表的实现。
 *          2.2 存储的是键值对映射。
 *          2.3 都继承了AbstractMap，实现了Map、Cloneable、Serializable。
 *          2.4 它们的构造函数都一样。
 *          2.5 默认的容量大小是16，默认的加载因子是0.75。
 *          2.6 都允许key和value为null。
 *          2.7 都是线程不安全的。
 *      3.与HashMap不同点：
 *          LinkedHashMap：
 *              1.多了双向链表的结构、有序，
 *              2.改变它迭代遍历时的顺序，在每次插入数据，或者访问、修改数据时，会增加节点、或调整链表的节点顺序。以决定迭代时输出的顺序，
 *              3.它与HashMap比，还有一个小小的优化，重写了containsValue()方法，直接遍历内部链表去比对value值是否相等;
 *              4.在put操作上,插入新Entry的同时，还会通过Entry的addBefore方法将其链入到双向链表中；
 *              5.扩容方面LinkedHashMap对其中的重哈希过程(transfer方法)进行了重写；
 *              6.在读取操作上重写了get方法，通过getEntry方法获取Entry对象，在此基础上，进一步获取指定键对应的值
 *
 *      4.为什么它不重写containsKey()方法，也去循环比对内部链表的key是否相等呢？
 *          HashMap最大的优点就是通过对key取hash来快速地位key在桶中的位置，这是结合了数组查找的优点，同时也是对链表节点查找的
 *          改进。所以如果LinkedHashMap覆写containsKey()方法，去循环比对内部链表的key是否相等，是低效的；
 *          hashMap中containsKey调用了getNode方法，它直接根据key计算出hash值，找到这个key的哈希桶，只需遍历这个哈希桶中有没有
 *          这个key。如果重写去遍历keySet集合反而效率更低了;
 *
 *      5.使用LinkedHashMap实现LRU缓存
 * 	        https://www.cnblogs.com/liuyang0/p/6664586.html
 *
 *      6.如何对LinkedHashMap进行反向遍历：使用的是迭代器 ListIterator，条件是hasPrevious()
 *
 *      7.同样地，调用LinkedHashMap的get(Object key)方法后，若返回值是 NULL，则也存在如下两种可能：
 *          6.1 该 key 对应的值就是 null;
 *          6.2 HashMap 中不存在该 key
 *
 *      8. LinkedHashMap为什么要实现Map接口？
 *          1.LinkedHashMap要保留Map这种数据结构的特性，因此它要实现Map所有的方法。
 *          2.LinkedHashMap是对HashMap中无序问题提出的改进，因此，它继承了HashMap。试想，如果你只继承了HashMap，而没有实现
 *              Map接口，那么是不是Map中的一些方法，LinkedHashMap可以不需要去实现的啊？那么LinkedHashMap保留Map这种数据结
 *              构的特性也就失去意义了。
 *          3.JDK的Collection源码里这种写法是很多的。其实我们必须要承认，这种写法是没有任何副作用的;
 *          4.但是这样写有一个好处，单独打开LinkedHashMap的源码，你就知道了它继承了哪个类，并实现了哪个接口。换句话说，不用去
 *              点开HashMap的源代码才能知道原来LinkedHashMap实现了Map。也就是，你不用在继承关系中苦苦徘徊，特别是当类与类之间
 *              的继承关系很复杂的时候
 *          5.这种出于人性化考虑的代码写法，还有一些例子，比如接口继承了接口，但子接口会显式声明父接口中的所有方法，并显式加上
 *              "@Override"这样的注解，以特别说明这个方法是从父接口继承而来的，跟我自己定义的接口没关系。
 *          6.在动态代理的时候会用到getInterfaces。因为Java的动态代理必须要求被代理类实现接口，Proxy.newProxyInstance()的第
 *              二个参数就是要接口数组，getInterfaces会在这里用到的
 * @author: cww
 * @DateTime: 2019/5/5 20:30
 */

public class LinkedHashMapTheory {
}
